`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    00:16:53 05/01/2012 
// Design Name: 
// Module Name:    coder 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module CODER(
		input wire systemclock,
		input wire reset,
		input wire chrCoderEn,
		input wire [24:0] chrCoderData,

		output reg coderFifoWrite,
		output reg [7:0] coderFifoData
		);

		reg [24:0] temp_reg = 25'b0;
		
		parameter s_idle = 2'b11;
		parameter s_0 = 2'b0;
		parameter s_1 = 2'b1;
		parameter s_dot = 2'b10;
		
		reg [1:0] state = s_idle;
		
		reg [27:0] BCD;
		reg [1:0] cnt_BCD = 2'b0;
		
		reg [4:0] top = 5'd23;
		reg [4:0] head;
		
		always @ ( posedge systemclock or posedge reset ) begin
			if ( reset ) begin
				state = s_idle;
				cnt_BCD = 2'b0;
				cnt_BCD = 2'b0;
				coderFifoWrite = 1'b0;
				top = 5'd23;
			end
			
			else begin
				case ( state )
					s_idle: begin
						coderFifoWrite = 1'b0;
						if ( chrCoderEn ) begin
							state = s_0;
							cnt_BCD = 2'b0;
							top = 5'd23;
							BCD = 0;
							head = 5'd27;
							if ( chrCoderData[24] ) begin
								temp_reg = ~chrCoderData + 1'b1;
								coderFifoWrite = 1'b1;
								coderFifoData = 8'h2d;
							end
							else begin
								temp_reg = chrCoderData;
								coderFifoWrite = 1'b0;
							end
						end
					end
					
					s_0: begin
						coderFifoWrite = 1'b0;
						BCD = {BCD[26:0],temp_reg[top]};
						if ( top == 4'b0 )
							state = s_1;
						else begin
							top = top - 1'b1;
							if ( BCD[3:0] > 4'd4 )
								BCD[3:0] = BCD[3:0] + 4'd3;
							if ( BCD[7:4] > 4'd4 )
								BCD[7:4] = BCD[7:4] + 4'd3;
							if ( BCD[11:8] > 4'd4 )
								BCD[11:8] = BCD[11:8] + 4'd3;
							if ( BCD[15:12] > 4'd4 )
								BCD[15:12] = BCD[15:12] + 4'd3;
							if ( BCD[19:16] > 4'd4 )
								BCD[19:16] = BCD[19:16] + 4'd3;
							if ( BCD[23:20] > 4'd4 )
								BCD[23:20] = BCD[23:20] + 4'd3;
							if ( BCD[27:24] > 4'd4 )
								BCD[27:24] = BCD[27:24] + 4'd3;
						end						
					end
					
					s_1: begin
						case ( head )
							5'd27: begin
								if ( BCD[27] | BCD[26] | BCD [25] | BCD[24] ) begin
									coderFifoWrite = 1'b1;
									coderFifoData = BCD[27:24] + 8'h30;
									cnt_BCD = cnt_BCD + 1'b1;
								end else
									coderFifoWrite = 1'b0;
							end
							
							5'd23, 5'd19, 
							5'd11, 5'd7: begin
								if ( cnt_BCD || (BCD[27] | BCD[26] | BCD [25] | BCD[24])) begin
									coderFifoWrite = 1'b1;
									coderFifoData = BCD[27:24] + 8'h30;
									if ( &cnt_BCD )
										state = s_idle;
									else
										cnt_BCD = cnt_BCD + 1'b1;
								end else
									coderFifoWrite = 1'b0;
							end
							
							5'd15, 5'd3: begin
								coderFifoWrite = 1'b1;
								coderFifoData = BCD[27:24] + 8'h30;
								if ( &cnt_BCD )
									state = s_idle;
								else begin
									state = s_dot;
									cnt_BCD = cnt_BCD + 1'b1;
								end
							end
							 
						endcase
						
						BCD = BCD << 4;
						head = head - 5'd4;
					end	
					
					s_dot: begin
						state = s_1;
						coderFifoWrite = 1'b1;
						coderFifoData = 8'h2e;
					end
				endcase
				
			end
		end		
			
endmodule 